home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / What's New? / Tool Chest / Text / WASTE 1.2a6 / WASTE Tabs / WETabHooks.c next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  6.2 KB  |  240 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    WETabHooks.c
  3.  *
  4.  *    Hooks for adding tab support to WASTE.
  5.  *    
  6.  *    Original code by Mark Alldritt
  7.  *    Line breaking code by Dan Crevier
  8.  *    Support for horizontal scrolling by Bert Seltzer
  9.  *    Maintenance by John C. Daub
  10.  *    Further modifications by Marco Piovanelli
  11.  *
  12.  */
  13.  
  14. #include "WETabHooks.h"
  15.  
  16. #ifndef kTabWidth
  17. #define    kTabWidth    32
  18. #endif
  19.  
  20. /*
  21.     If kTabWidth is a power of two, we can exploit the fact that
  22.         (x % kTabWidth) == (x & (kTabWidth - 1))
  23.     and replace those expensive modulus (%) operators with much
  24.     cheaper ANDs.  (From a suggestion by Mark Valence.)
  25. */
  26.  
  27. #define IS_POWER_OF_TWO(x)        (((x) & ((x) - 1)) == 0)
  28.  
  29. #if IS_POWER_OF_TWO(kTabWidth)
  30.     /* inline short MOD(short x) { return (x & (kTabWidth - 1)); } */
  31.     #define MOD(x)                (((short) (x)) & (kTabWidth - 1))
  32. #else
  33.     /* inline short MOD(short x) { return (x % kTabWidth); } */
  34.     #define MOD(x)                (((short) (x)) % kTabWidth)
  35. #endif
  36.  
  37. /* inline short FIXROUND(Fixed f) { return ((f + 0x00008000) >> 16); } */
  38. #define FIXROUND(f)        ((short) (((f) + 0x00008000) >> 16))
  39.  
  40. pascal void _WETabDrawText(Ptr pText, long textLength, Fixed slop,
  41.                 JustStyleCode styleRunPosition, WEHandle hWE)
  42. {
  43. #pragma unused(slop, styleRunPosition)
  44.  
  45.     long beginChar = 0;
  46.     long ii;
  47.     short tabWidth;
  48.     short destLeft;
  49.     Point penPos;
  50.     
  51.     destLeft = (short) (*hWE)->destRect.left;
  52.     
  53.     for ( ii = 0; ii < textLength; ii++ )
  54.     {
  55.         if (pText[ii] == '\t')
  56.         {
  57.             DrawText(pText, beginChar, ii - beginChar);
  58.  
  59.             /* advance the pen to the next tab stop */
  60.             GetPen(&penPos);
  61.             tabWidth = kTabWidth - MOD(penPos.h - destLeft);
  62.             MoveTo(penPos.h + tabWidth, penPos.v);
  63.             beginChar = ii + 1;
  64.         }
  65.     }    /* for */
  66.  
  67.     DrawText(pText, beginChar, textLength - beginChar);
  68. }
  69.  
  70. pascal long _WETabPixelToChar(Ptr pText, long textLength, Fixed slop,
  71.                 Fixed *width, char *edge, JustStyleCode styleRunPosition,
  72.                 Fixed hPos, WEHandle hWE)
  73. {
  74. #pragma unused(hWE)
  75.  
  76.     long beginChar = 0;
  77.     long offset = 0;
  78.     long ii;
  79.     Fixed lastWidth;
  80.     Fixed tabWidth;
  81.     
  82.     /* loop through every character in the segment looking for tabs */
  83.     for ( ii = 0; ii < textLength; ii++ )
  84.     {
  85.         /* exit now if width has gone negative */
  86.         /* (i.e., if we have found which glyph was hit) */
  87.         if (*width <= 0)
  88.             break;
  89.  
  90.         /* tab found? */
  91.         if (pText[ii] == '\t')
  92.         {
  93.             /* calculate the width of the sub-segment preceding the tab */
  94.             lastWidth = *width;
  95.             offset += PixelToChar(pText + beginChar, ii - beginChar, slop,
  96.                     lastWidth, (unsigned char *) edge, width, styleRunPosition,
  97.                     kOneToOneScaling, kOneToOneScaling);
  98.             beginChar = ii + 1;
  99.  
  100.             /* hit point past sub-segment? */
  101.             if (*width >= 0)
  102.             {
  103.                 /* increment hPos by width of sub-segment preceding the tab */
  104.                 hPos += (lastWidth - *width);
  105.                 
  106.                 /* calculate the width of the tab "glyph" (as a Fixed value) */
  107.                 tabWidth = BSL(kTabWidth - MOD(FIXROUND(hPos)), 16);
  108.                 
  109.                 /* increment hPos by width of tab character */
  110.                 hPos += tabWidth;
  111.                 
  112.                 /* hit point within tab glyph? */
  113.                 if (*width < tabWidth)
  114.                 {
  115.                     /* yes: determine which half of tab glyph was hit */
  116.                     if (*width > (tabWidth >> 1))
  117.                     {
  118.                         *edge = kTrailingEdge;    /* second (trailing) edge of tab */
  119.                         offset++;
  120.                     }
  121.                     else
  122.                         *edge = kLeadingEdge;    /* first (leading) edge of tab */
  123.                     
  124.                     /* returning -1 (as Fixed) in width means we're finished */
  125.                     *width = 0xFFFF0000;
  126.                 }
  127.                 else {
  128.                     /* hit point is past tab: keep looping */
  129.                     offset++;
  130.                     *width -= tabWidth;
  131.                 }
  132.             } /* if (*width >= 0) */
  133.         } /* if tab found */
  134.     } /* for */
  135.     
  136.     /* no more tabs in this segment: process the last sub-segment */
  137.     if (*width >= 0)
  138.     {
  139.         lastWidth = *width;
  140.         offset += PixelToChar(pText + beginChar, textLength - beginChar, slop,
  141.                     lastWidth, (unsigned char *) edge, width, styleRunPosition,
  142.                     kOneToOneScaling, kOneToOneScaling);
  143.     }
  144.     
  145.     /* round width to nearest integer value */
  146.     /* this is supposed to fix an incompatibility with the WorldScript Power Adapter */
  147.     *width = (*width + 0x00008000) & 0xFFFF0000;
  148.     
  149.     return offset;
  150. }
  151.  
  152. pascal short _WETabCharToPixel(Ptr pText, long textLength, Fixed slop,
  153.                 long offset, short direction, JustStyleCode styleRunPosition,
  154.                 long hPos, WEHandle hWE)
  155. {
  156. #pragma unused(slop, direction, styleRunPosition)
  157.  
  158.     long beginChar = 0;
  159.     long ii;
  160.     short width;
  161.     short destLeft;
  162.     short totalWidth = 0;
  163.  
  164.     destLeft = (short) (*hWE)->destRect.left;
  165.  
  166.     /* measure text up to offset, if offset is within this segment */
  167.     if (offset < textLength)
  168.         textLength = offset;
  169.     
  170.     for ( ii = 0; ii < textLength; ii++ )
  171.     {
  172.         if (pText[ii] == '\t')
  173.         {
  174.             /* calculate the pixel width of the subsegment preceding the tab */
  175.             width = TextWidth(pText, beginChar, ii - beginChar);
  176.             totalWidth += width;
  177.             hPos += width;
  178.             
  179.             /* calculate tab width */
  180.             width = kTabWidth - MOD(hPos - destLeft);
  181.             totalWidth += width;
  182.             hPos += width;
  183.             
  184.             /* go to next subsegment */
  185.             beginChar = ii + 1;
  186.         }
  187.     } /* for */
  188.     
  189.     /* calculate width of remaining characters */
  190.     width = TextWidth(pText, beginChar, textLength - beginChar);
  191.     totalWidth += width;
  192.     
  193.     return totalWidth;
  194. }
  195.  
  196. pascal StyledLineBreakCode _WETabLineBreak(Ptr pText, long textLength,
  197.             long textStart, long textEnd, Fixed *textWidth,
  198.             long *textOffset, WEHandle hWE)
  199. {
  200.     long beginChar = textStart;
  201.     long ii;
  202.     Fixed tabWidth;
  203.     short destWidth;
  204.     StyledLineBreakCode breakCode = smBreakOverflow;
  205.     
  206.     destWidth = (short) ((*hWE)->destRect.right - (*hWE)->destRect.left);
  207.     
  208.     for ( ii = textStart; ii < textEnd; ii++ )
  209.     {
  210.         if (pText[ii] == '\t')
  211.         {
  212.             /* do previous "segment" */
  213.             breakCode = StyledLineBreak(pText, textLength, beginChar,
  214.                             ii, 0, textWidth, textOffset);
  215.             if ((breakCode != smBreakOverflow) || (ii >= textLength))
  216.                 break;
  217.             beginChar = ii + 1;
  218.             
  219.             /* calculate tab width (as a Fixed value) */
  220.             tabWidth = BSL(kTabWidth - MOD(destWidth - FIXROUND(*textWidth)), 16);
  221.             
  222.             /* if tabWidth > pixelWidth we break in tab */
  223.             /* don't move tab to next line */
  224.             if (tabWidth > *textWidth)
  225.             {
  226.                 breakCode = smBreakWord;
  227.                 *textOffset = ii + 1;
  228.                 break;
  229.             }
  230.             else
  231.                 *textWidth -= tabWidth;
  232.         }
  233.     } /* for */
  234.  
  235.     /* do last sub-segment */
  236.     if ((ii - beginChar >= 0) && (breakCode == smBreakOverflow))
  237.         breakCode = StyledLineBreak(pText, textLength, beginChar, ii, 0, textWidth, textOffset);
  238.     
  239.     return breakCode;
  240. }